package com.Cfeng.XiaohuanChat.util;

import com.mysql.cj.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.lionsoul.ip2region.DataBlock;
import org.lionsoul.ip2region.DbConfig;
import org.lionsoul.ip2region.DbSearcher;
import org.lionsoul.ip2region.Util;
import org.springframework.core.io.ClassPathResource;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author Cfeng
 * @date 2022/8/21
 *
 * 根据IP离线查询地址， 调用IpRegion2Util进行查询
 */

@Slf4j
public class RegionUtil {

    //jar临时文件夹
    private static final String JAVA_TEMP_DIR = "java.io.tmpdir";

    static DbConfig config = null;

    static DbSearcher searcher = null;

    //使用一个静态代码块让第一次加载的时候就读取资源，使用class.getResouce
    static {
        //项目中直接在static下面 即/ip2region.db
        //jar无法读取文件，需要复制创建临时文件,绝对path
        try {
            String path = RegionUtil.class.getResource("/static/ip2region.db").getPath();
            File file = new File(path);
            //文件不存在就加上jar的临时目录重新读取到file中
            if(!file.exists()) {
                String tmpDir = System.getProperties().getProperty(JAVA_TEMP_DIR);
                path = tmpDir + "ip2region.db";
                file = new File(path);
                ClassPathResource classPathResource = new ClassPathResource("static" + File.separator + "ip2region.db");
                //通过流获取File
                InputStream resourceStream = classPathResource.getInputStream();
                if(resourceStream != null) {
                    FileUtils.copyInputStreamToFile(resourceStream,file);
                }
            }
            config = new DbConfig(); //region的config
            searcher = new DbSearcher(config,path); //创建seacher
            log.info("bean create success, {},{}",config,searcher);
        } catch (Exception e) {
            log.error("init ip region error {}",e);
        }
    }

    /**
     * 解析IP地址
     */
    public static String getRegion(String ip) {
        try {

            if(Objects.isNull(searcher) || StringUtils.isNullOrEmpty(ip)) {
                log.error("Dbsearcher is null");
                return "";
            }
            long startTime = System.currentTimeMillis();
            // 查询算法,使用反射动态选择方法
            int algorithm = DbSearcher.MEMORY_ALGORITYM;
            Method method = null;
            switch (algorithm)
            {
                case DbSearcher.BTREE_ALGORITHM:
                    method = searcher.getClass().getMethod("btreeSearch", String.class);
                    break;
                case DbSearcher.BINARY_ALGORITHM:
                    method = searcher.getClass().getMethod("binarySearch", String.class);
                    break;
                case DbSearcher.MEMORY_ALGORITYM:
                    method = searcher.getClass().getMethod("memorySearch", String.class);
                    break;
            }

            DataBlock dataBlock = null;
            if (Util.isIpAddress(ip) == false)
            {
                log.warn("warning: Invalid ip address");
            }
            dataBlock = (DataBlock) method.invoke(searcher, ip);
            String result = dataBlock.getRegion();
            long endTime = System.currentTimeMillis();
            log.debug("regionSearch use time[{}] result[{}]", endTime - startTime, result);
            return result;
        } catch (Exception e) {
            log.error("error:{}",e);
        }
        return "";
    }
}
